package com.baofu.paycore.manager.storer.impl;

import com.baofu.paycore.common.enums.FundTypeEnum;
import com.baofu.paycore.common.exception.PayCoreBizException;
import com.baofu.paycore.manager.model.preAuth.SubPreAuthBO;
import com.baofu.paycore.service.facade.enums.PayCoreErrorCode;
import com.baofu.paycore.dal.mapper.PreAuthMapper;
import com.baofu.paycore.dal.mapper.SubPreAuthMapper;
import com.baofu.paycore.dal.model.PreAuthDO;
import com.baofu.paycore.dal.model.SubPreAuthDO;
import com.baofu.paycore.dal.model.base.BaseDO;
import com.baofu.paycore.manager.converter.BO2DOConverter;
import com.baofu.paycore.manager.converter.DO2BOConverter;
import com.baofu.paycore.manager.model.preAuth.PreAuthBO;
import com.baofu.paycore.manager.storer.AbstractOrderRepository;
import com.baofu.paycore.manager.storer.PreAuthRepository;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 预授权处理
 *
 * <p>
 *  1.订单转换
 *  2.加载并锁定订单
 *  3.加载订单
 *  4.幂等性校验
 *  5.获取预授权信息
 *  6.依原支付单号查询预授权信息
 *  7.更新预授权撤销信息
 * </p>
 * User: xin deng  Date: 16/8/30 ProjectName: paycore Version: 1.0
 */
@Slf4j
@Component
public class PreAuthRepositoryImpl extends AbstractOrderRepository<PreAuthBO> implements PreAuthRepository {

    /**
     * 预授权mapper
     */
    @Autowired
    private PreAuthMapper preAuthMapper;

    /**
     * 预授权子订单mapper
     */
    @Autowired
    private SubPreAuthMapper subPreAuthMapper;

    /**
     * 订单转换
     *
     * @param payBaseBO 支付对象
     * @return 转换后DO
     */
    @Override
    protected List<? extends BaseDO> convertToDO(PreAuthBO payBaseBO) {

        List<BaseDO> list = Lists.newArrayList();
        PreAuthDO preAuthDO = BO2DOConverter.preAuthBOToDO(payBaseBO);
        List<SubPreAuthDO> subPreAuthDO = BO2DOConverter.subPreAuthBOToDO(payBaseBO);
        list.add(preAuthDO);
        if (subPreAuthDO != null){
            list.addAll(subPreAuthDO);
        }
        return list;
    }

    /**
     * 加载并锁定订单
     *
     * @param requestOrderNo 请求订单号
     * @param requestBizNo   请求流水号
     * @return 支付信息
     */
    @Override
    public PreAuthBO lock(String requestOrderNo, String requestBizNo,String requestSystem) {
        return null;
    }

    /**
     * 加载订单
     *
     * @param payNo 支付单号
     * @return 订单
     */
    @Override
    public PreAuthBO load(String payNo) {
        PreAuthDO preAuthDO = preAuthMapper.selectByPayNo(payNo);
        if (null == preAuthDO){
            log.error("加载预授权订单 不存在 支付单号:{}", payNo);
            throw new PayCoreBizException(PayCoreErrorCode.ORDER_IS_NOT_EXISTED);
        }
        List<SubPreAuthDO> subPreAuthDOS = subPreAuthMapper.selectSubsByPayNo(payNo);
        PreAuthBO preAuthBO = DO2BOConverter.preAuthDO2BOConverter(preAuthDO);
        List<SubPreAuthBO> subPreAuthBOS=new ArrayList<>();
        for (SubPreAuthDO subPreAuthDO:subPreAuthDOS){
            subPreAuthBOS.add(DO2BOConverter.subPreAuthDO2BOConverter(subPreAuthDO));
        }
        preAuthBO.setSubPreAuthBO(subPreAuthBOS);

        return preAuthBO;
    }

    /**
     * 幂等性校验
     *
     * @param requestBizNo   请求流水号
     * @param requestOrderNo 请求清单号
     * @return 订单
     */
    @Override
    public PreAuthBO checkIdempotent(String requestBizNo, String requestOrderNo,String requestSystem) {
        PreAuthDO preAuthDO = preAuthMapper.selectByOrderNo(requestOrderNo, requestBizNo,requestSystem);
        return DO2BOConverter.preAuthDO2BOConverter(preAuthDO);
    }

    /**
     * 获取预授权信息
     *
     * @param origPayNo         原支付单号
     * @param origRequestDate   原请求日期
     * @param origRequestBizNo  原请求业务编号
     * @param origOrderNo       原订单号
     * @param origRequestSystem 原请求系统
     * @return 预授权信息
     */
    @Override
    public PreAuthBO getPreAuthByOrig(String origPayNo, Date origRequestDate, String origRequestBizNo,
                                      String origOrderNo, String origRequestSystem) {
        PreAuthDO preAuthDO = new PreAuthDO();
        preAuthDO.setPayNo(origPayNo);
        preAuthDO.setRequestBizNo(origRequestBizNo);
        preAuthDO.setRequestSystem(origRequestSystem);
        preAuthDO.setRequestOrderNo(origOrderNo);
        preAuthDO.setRequestDate(origRequestDate);

        preAuthDO = preAuthMapper.selectByParams(preAuthDO);

        return DO2BOConverter.preAuthDO2BOConverter(preAuthDO);
    }

    /**
     * 依原支付单号查询预授权信息
     *
     * @param origPayNo 原支付单号
     * @return 预授权信息
     */
    @Override
    public PreAuthBO getPreAuthByOrigPayNo(String origPayNo) {

        PreAuthDO preAuthDO = preAuthMapper.selectByOrigPayNo(origPayNo);

        return DO2BOConverter.preAuthDO2BOConverter(preAuthDO);
    }

    /**
     * 更新预授权撤销信息
     *
     * @param preAuthBO 预授权信息
     */
    @Override
    @Transactional(readOnly = false, isolation = Isolation.DEFAULT,
            propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void updatePreAuthCancel(PreAuthBO preAuthBO) {
        PreAuthDO preAuthDO = BO2DOConverter.preAuthBOToDO(preAuthBO);
        preAuthMapper.update(preAuthDO);
        List<SubPreAuthDO> subPreAuthDOs = BO2DOConverter.subPreAuthBOToDO(preAuthBO);
        if (subPreAuthDOs != null){
            subPreAuthDOs.forEach(subPreAuthDO -> subPreAuthMapper.update(subPreAuthDO));
        }
        PreAuthDO authDO = new PreAuthDO();
        authDO.setOrigPayNo(preAuthBO.getOrigPayNo());
        authDO.setDealAmt(preAuthBO.getAmt());
        preAuthMapper.updateDealAmt(authDO);
    }
}
